﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using KAImage;
using KAImage.Config;
using KAImage.Algorithms;

namespace IPCPhotoEditor
{
    public partial class FormCurves : Form
    {
        private ImageCurveOption _option = null;
        public ImageCurveOption Option
        {
            get
            {
                return _option;
            }          
        }

        private Pen blackPen = new Pen(Color.Gray, 1);

        private HistogramBackground _backgroundCreator = null;

        private Bitmap _sourceImage = null;

        private Bitmap _destImage = null;

        private int _guideLines = 1;

        private int _baseLine = 1;

        private int _histogram = 1;
   
        private CurveControl _curveControl = null;

        /// <summary>
        /// 指示曲线中正在编辑的点是不是拖动修改的
        /// 如果不是拖动修改，就是通过输入位置值直接修改
        /// </summary>
        private bool _pointDragModified = false;

        public WorkImageUpdatedEventHandler WorkImageUpdated = null;

        protected void OnWorkImageUpdated(Bitmap image)
        {
            if (WorkImageUpdated != null)
            {
                WorkImageUpdated(this, new WorkImageUpdatedEventArgs(image));
            }
        }

        public FormCurves(Bitmap bmp)
        {
            _sourceImage = bmp.Clone() as Bitmap;
            InitializeComponent();
            _curveControl = new CurveControl();
            _backgroundCreator = new HistogramBackground(_sourceImage);          
        }

        public FormCurves()
        {
            _option = KAConfigs.Curves;
            InitializeComponent();
            _curveControl = new CurveControl();
            //_backgroundCreator = new HistogramBackground(_sourceImage);
        }

        private void InitCtrls()
        {

        }

        public void Curve_Updated(object sender, CurveUpdatedEventArgs e)
        {
            OnCurveValueChanged();
        }

        private void mouseLocation_Reported(object sender, MouseLocationReportedEventArgs e)
        {
            _pointDragModified = true;
            textBoxInput.Text = e.Location.X.ToString();
            textBoxOutput.Text = e.Location.Y.ToString();
            _pointDragModified = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.SelectedIndex = 0;
            comboBoxPreinstallCurves.SelectedIndex = 0;

            panelGridLines.Controls.Add(_curveControl);
            _curveControl.Location = new Point(0, 0);
            _curveControl.Parent = panelGridLines;
            _curveControl.BackColor = Color.Transparent;

            _curveControl.MouseLocReported += mouseLocation_Reported;           
            _guideLines = 1;

            if (_option != null)
            {
                _curveControl.ApplySettings(_option);
            }

            if (_sourceImage == null)
            {
                buttonAuto.Visible = false;
                buttonAutoOptions.Visible = false;
                buttonLoad.Visible = false;
            }
            else
            {
                _curveControl.CurveUpdated += Curve_Updated;
                buttonLoad.Visible = true;
            }
        }

        private void DisposeImage()
        {
            if (_sourceImage != null)
            {
                _sourceImage.Dispose();
                _sourceImage = null;
            }         
            if (_destImage != null)
            {
                _destImage.Dispose();
                _destImage = null;
            }
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {          
            _curveControl.MouseLocReported -= mouseLocation_Reported;
            _curveControl.CurveUpdated -= Curve_Updated;
            _curveControl.StopBackgroudWorking();
            DisposeImage();
            if (_backgroundCreator != null)
            {
                _backgroundCreator.Dispose();
                _backgroundCreator = null;
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            _curveControl.ColorChannel = comboBox1.SelectedIndex;
            if (checkBoxHistogram.Checked)
            {
                _histogram = comboBox1.SelectedIndex + 1;
            }
            else
            {
                _histogram = 0;
            }
            SetPanelBackground();
            _curveControl.Invalidate();
        }

        private void OnCurveValueChanged()
        {
            if(_destImage != null)
            {
                _destImage.Dispose();
                _destImage = null;
            }
            if (_destImage == null)
            {
                _destImage = _sourceImage.Clone() as Bitmap;
            }
            if(!_curveControl.splines[0].IsEmpty)
            {
                ImageAdjustments.ApplyMappingToRGB(_destImage, _curveControl.splines[0].Mapping);
            }
            if (!_curveControl.splines[1].IsEmpty)
            {
                ImageAdjustments.ApplyMappingToR(_destImage, _curveControl.splines[1].Mapping);
            }
            if (!_curveControl.splines[2].IsEmpty)
            {
                ImageAdjustments.ApplyMappingToG(_destImage, _curveControl.splines[2].Mapping);
            }
            if (!_curveControl.splines[3].IsEmpty)
            {
                ImageAdjustments.ApplyMappingToB(_destImage, _curveControl.splines[3].Mapping);
            }        
            OnWorkImageUpdated(_destImage.Clone() as Bitmap);                
        }

        private void buttonDrawNatual_Click(object sender, EventArgs e)
        {
            _curveControl.ResetPoints();
            if (_option != null)
            {
                _option = _curveControl.CreatConfigOption();
                _option.Save();
            }
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }
    
        private void DrawCoordinateSystem()
        {
            using (Graphics g = panelOutcome.CreateGraphics())
            {
                Color FColor = Color.White;
                Color TColor = Color.Black;
                Brush b = new LinearGradientBrush(panelOutcome.ClientRectangle, FColor, TColor, LinearGradientMode.Vertical);
                g.FillRectangle(b, panelOutcome.ClientRectangle);
            }
            using (Graphics g = panelInput.CreateGraphics())
            {
                Color FColor = Color.Black;
                Color TColor = Color.White;
                Brush b = new LinearGradientBrush(panelInput.ClientRectangle, FColor, TColor, LinearGradientMode.Horizontal);
                g.FillRectangle(b, panelInput.ClientRectangle);
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            DrawCoordinateSystem();
        }

        private void SetPanelBackground()
        {
            if (panelGridLines.BackgroundImage != null)
            {
                panelGridLines.BackgroundImage.Dispose();
                panelGridLines.BackgroundImage = null;
            }
            if (_backgroundCreator != null)
            {
                panelGridLines.BackgroundImage = _backgroundCreator[_baseLine, _guideLines, _histogram];
            }
        }

        private void buttonQuartering_Click(object sender, EventArgs e)
        {
            _guideLines = 1;
            SetPanelBackground();
        }

        private void buttonTen_Click(object sender, EventArgs e)
        {
            _guideLines = 2;
            SetPanelBackground();
        }

        private void checkBoxHistogram_CheckedChanged(object sender, EventArgs e)
        {
            _histogram = checkBoxHistogram.Checked ? 1 : 0;
            SetPanelBackground();
        }

        private void checkBoxBaseLine_CheckedChanged(object sender, EventArgs e)
        {
            _baseLine = checkBoxBaseLine.Checked ? 1 : 0;
            SetPanelBackground();
        }

        private void buttonCancell_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }

        private void buttonAuto_Click(object sender, EventArgs e)
        {
            AutoAdjusting autoAdj = new AutoAdjusting(_sourceImage);
            if (_destImage != null)
            {
                _destImage.Dispose();
                _destImage = null;
            }
            _destImage = autoAdj.AutoContrast();
            OnWorkImageUpdated(_destImage.Clone() as Bitmap);
        }

        private void buttonAutoOptions_Click(object sender, EventArgs e)
        {
            FormAutoAdjustOptions form = new FormAutoAdjustOptions(0);
            form.ShowDialog();
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            ImageCurveOption option = _curveControl.CreatConfigOption();
            if (option.Save())
            {
                MessageBox.Show("设置已保存.");
            }
        }

        private void textBoxInput_TextChanged(object sender, EventArgs e)
        {
            UpdateCurveFocusPoint();
        }

        private void textBoxOutput_TextChanged(object sender, EventArgs e)
        {
            UpdateCurveFocusPoint();
        }

        private void UpdateCurveFocusPoint()
        {
            if (_pointDragModified
               || _curveControl.TheSpline.IsEmpty
               || !_curveControl.TheSpline.ActiveEditing
               || string.IsNullOrEmpty(textBoxInput.Text)
               || string.IsNullOrEmpty(textBoxOutput.Text))
            {
                return;
            }
            int x = int.Parse(textBoxInput.Text);
            int y = int.Parse(textBoxOutput.Text);
            _curveControl.SetCurvePointAction(new Point(x, y), CurvePointAction.Update);
        }
     
        private void textBox_Validating(object sender, CancelEventArgs e)
        {
            TextBox box = sender as TextBox;
            int val, min = 0, max = 255;
            if (box == textBoxInput)
            {
                min = 4;
                max = 251;
            }
            if (int.TryParse(box.Text, out val))
            {
                if (val < min || val > max)
                {
                    string infoErr = string.Format("请输入一个[{0},{1}]范围内的整数.", min, max);
                    errorProvider1.SetError(box, infoErr);
                }
                else
                {
                    //Value = val;
                    errorProvider1.SetError(box, "");
                }
            }
            else
            {
                errorProvider1.SetError(box, "不是合法的数字!");
                box.Focus();
            }
        }

        private void textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\b'
               || Char.IsDigit(e.KeyChar)
               || Char.IsControl(e.KeyChar)
               || e.KeyChar == 46)
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            _curveControl.SetCurvePointAction(new Point(), CurvePointAction.Remove);
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            _curveControl.SetCurvePointAction(new Point(), CurvePointAction.Clear);
        }

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            ImageCurveOption option = KAConfigs.Curves;
            option.Load();
            _curveControl.ApplySettings(option);
            _curveControl.Invalidate();
            OnCurveValueChanged();
        }
    }
}

//Graphics g = panel1.CreateGraphics();
////画一个椭圆
//g.DrawImage(image, new Rectangle(0, 0, 200, 240), new Rectangle(400,1000, 200, 240), GraphicsUnit.Pixel);
//g.Dispose();
